package com.email.box.codeGenerator;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * 代码生成器
 *
 * @author liza
 */
public class CodeGenerator {

    /**
     * 作者
     */
    private static final String AUTHOR = "xuan";

    /**
     * 数据库配置
     */
    public static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
    public static final String URL = "jdbc:mysql://localhost:3306/email?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";
    public static final String USERNAME = "root";
    public static final String PASSWORD = "qqcf258..";

    /**
     * 包路径 & 模块名 & 表名
     */
    private static final String PARENT = "com.email";
    private static final String MODULE_NAME = "box";
    private static final String[] TABLE_NAMES = {
            "sys_user_info"
    };

    /**
     * 是否更新实体PO(表结构更改，重新覆盖生成PO，其他文件没有变化)
     */
    private static final boolean ONLY_CREATE_ENTITY_PO = false;

    /**
     * 是否生成crud方法(输入x,自动生成service层crud方法)
     */
    private static final String ONLY_CREATE_CRUD_METHOD = "x";

    /**
     * 表填充字段 & 逻辑删除字段
     */
    private static List<TableFill> tableFills = new ArrayList<>() {{
        add(new TableFill("creator", FieldFill.INSERT));
        add(new TableFill("modifier", FieldFill.INSERT_UPDATE));
        add(new TableFill("entry_time", FieldFill.INSERT));
        add(new TableFill("update_time", FieldFill.INSERT_UPDATE));
        add(new TableFill("status", FieldFill.INSERT));
    }};
    private static final String LOGIC_DELETE_FIELD_NAME = "status";

    public static void main(String[] args) {
        // 控制台执行
        Scanner scan = new Scanner(System.in);
        System.out.println("驱动：\t" + DRIVER_NAME);
        System.out.println("Url：\t" + URL);
        System.out.println("用户名：\t" + USERNAME);
        System.out.println("密码： \t" + PASSWORD);
        System.out.println("表：\t" + Arrays.toString(TABLE_NAMES));
        if (ONLY_CREATE_ENTITY_PO) {
            System.out.println("************更新实体PO************");
        } else {
            System.out.println("************生成所有文件***********");
        }
        System.out.println("是否继续？");
        String s = scan.nextLine();
        if ("".equals(s)) {
            if (ONLY_CREATE_ENTITY_PO) {
                codeGenerator(TABLE_NAMES, true, true, "entity.po", "%sPO", "templates/entity.java");
            } else {
                codeGenerator(TABLE_NAMES, true, false, "entity.converter", "%sConverter", "templates/converter.java");
                codeGenerator(TABLE_NAMES, false, false, "entity.po", "%sPO", "templates/entity.java");
            }
        } else if (ONLY_CREATE_CRUD_METHOD.equals(s)) {
            codeGenerator(TABLE_NAMES, true, true, "entity.converter", "%sConverter", "templates/tag/converter.java");
            codeGenerator(TABLE_NAMES, true, "entity.po", "%sPO", "templates/entity.java", "templates/tag/service.java", "templates/tag/serviceImpl.java", "templates/tag/controller.java");
            codeGenerator(TABLE_NAMES, true, true, "entity.dto", "Save%sDTO", "templates/tag/entity.java");
            codeGenerator(TABLE_NAMES, true, true, "entity.vo", "Get%sListVO", "templates/tag/entity.java");
            codeGenerator(TABLE_NAMES, true, true, "entity.po", "%sPO", "templates/entity.java");
        }
        scan.close();
    }

    public static void codeGenerator(String[] tableNames, boolean onlyCreateEntity, boolean fileOverride,
                                     String entity, String entityName, String entityTemplate) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 选择模板
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());

        // 配置自定义输出模板
        if (!onlyCreateEntity) {
            //自定义xml文件
            getInjectionConfigConfig(mpg);
            mpg.setTemplate(new TemplateConfig()
                    .setEntity(entityTemplate)
                    .setMapper("templates/mapper.java")
                    .setController(null)
                    .setXml(null)
            );
        } else {
            mpg.setTemplate(new TemplateConfig()
                    .setEntity(entityTemplate)
                    .setMapper(null)
                    .setService(null)
                    .setServiceImpl(null)
                    .setController(null)
                    .setXml(null)
            );
        }

        // 数据源配置
        setDefaultAutoGenerator(tableNames, mpg, fileOverride, entity, entityName);

        // 执行
        mpg.execute();
    }

    public static void codeGenerator(String[] tableNames, boolean fileOverride, String entity, String entityName,
                                     String entityTemplate, String serviceTemplate, String serviceImplTemplate, String controllerTemplate) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 选择模板
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());

        // 配置自定义输出模板
        mpg.setTemplate(new TemplateConfig()
                .setEntity(entityTemplate)
                .setMapper("templates/mapper.java")
                .setService(serviceTemplate)
                .setServiceImpl(serviceImplTemplate)
                .setController(controllerTemplate)
                .setXml(null)
        );

        // 数据源配置
        setDefaultAutoGenerator(tableNames, mpg, fileOverride, entity, entityName);

        // 执行
        mpg.execute();
    }

    private static void setDefaultAutoGenerator(String[] tableNames, AutoGenerator mpg, boolean fileOverride, String entity, String entityName) {
        mpg.setDataSource(new DataSourceConfig()
                .setDriverName(DRIVER_NAME)
                .setUrl(URL)//url
                .setUsername(USERNAME)
                .setPassword(PASSWORD)
                .setTypeConvert((globalConfig, fieldType) -> {
                    String t = fieldType.toLowerCase();
                    if (t.contains("datetime")) {
                        return DbColumnType.LOCAL_DATE_TIME;
                    }
                    if (t.contains("timestamp")) {
                        return DbColumnType.LOCAL_DATE_TIME;
                    }
                    //其它字段采用默认转换（非mysql数据库可以使用其它默认的数据库转换器）
                    return new MySqlTypeConvert().processTypeConvert(globalConfig, fieldType);
                })
        );

        // 全局配置
        mpg.setGlobalConfig(new GlobalConfig()
                .setOutputDir(System.getProperty("user.dir") + "/src/main/java")
                //是否打开输出目录
                .setOpen(false)
                //作者
                .setAuthor(AUTHOR)
                //是否覆盖文件
                .setFileOverride(fileOverride)
                //是否使用swagger2
                .setSwagger2(true)
                //实体类后缀
                .setEntityName(entityName)
        );

        // 包配置
        mpg.setPackageInfo(new PackageConfig()
                //包路径
                .setParent(PARENT)
                //模块路径
                .setModuleName(MODULE_NAME)
                //实体路径
                .setEntity(entity)
        );

        // 策略配置
        mpg.setStrategy(new StrategyConfig()
                //表名下划线转驼峰
                .setNaming(NamingStrategy.underline_to_camel)
                //字段名下划线转驼峰
                .setColumnNaming(NamingStrategy.underline_to_camel)
                //表前缀
                .setTablePrefix("")
                //需要生成的表
                .setInclude(tableNames)
                //lombok依赖
                .setEntityLombokModel(true)
                //设置实体序列号UID
                .setEntitySerialVersionUID(true)
                //@TableField注解
                .setEntityTableFieldAnnotationEnable(true)
                //表填充字段
                .setTableFillList(tableFills)
                //逻辑删除字段
                .setLogicDeleteFieldName(LOGIC_DELETE_FIELD_NAME)
                //@Controller -> @RestController
                .setRestControllerStyle(true)
                //设置控制器映射连字符样式
                .setControllerMappingHyphenStyle(true)
        );
    }


    public static void getInjectionConfigConfig(AutoGenerator mpg) {
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return System.getProperty("user.dir")
                        + "/src/main/resources/mapper/"
                        + mpg.getPackageInfo().getModuleName() + "/"
                        + tableInfo.getMapperName()
                        + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
    }
}
